#[macro_use] extern crate structopt;
extern crate usrtrust;

use structopt::StructOpt;
use usrtrust::{CPBuffer,Mem,CMem,Fifo,Log,Environment,ULogs};
use std::path::{Path,PathBuf};
use std::io::Write;
use std::{thread, time};
use std::sync::mpsc;

#[derive(Debug, StructOpt)]
#[structopt(name = "MayApp", about = "An example of StructOpt usage.")]
struct Opt {
    #[structopt(short = "f"
        , long = "file"
        , default_value="c349e642-6b66-5eaf-a82a-369a5cb5b9c5"
        , parse(from_str)
    )]
    file: String,
}

fn main() -> std::io::Result<()> {
    let opt = Opt::from_args();
    println!("{}",std::mem::size_of::<CPBuffer>());
    let mut path = PathBuf::new();
    path.push("/tmp/usrtos");
    path.push(opt.file);
    let p = path.into_os_string().into_string().unwrap();
    let h = CPBuffer::attach(p.clone())?;
    println!("{}",h); 
    let mut m = Mem::attach(p.clone())?;
    println!("{}",m); 
    for i in 0..4 {
        let gp = m.new::<usize>()?;
        println!("{}",gp);
    }
    for i in 0..4 {
        let gp = m.new_gp(8_usize)?;
        println!("{}",gp);
    }
    let mut cm = CMem::attach(p.clone())?;
    println!("{}",cm); 
    for i in 0..4 {
        let gp = cm.new::<usize>()?;
        println!("{}",gp);
    }
    let mut f = Fifo::attach(p.clone())?;
    println!("{}",f); 
    f.local_reset();
    for i in 0..4 {
        let mut gp = f.new::<usize>()?;
        *gp = i;
        f.push(&gp);
        println!("{}",gp);
    }
    for i in 0..5 {
        let gp = f.local_get::<usize>()?;
        match gp {
            Some(mp) => println!("{}",*mp),
            None => println!("None"),
        }
    }
    f.sync();
    for i in 0..5 {
        let gp = f.get::<usize>()?;
        match gp {
            Some(mp) => println!("{}",*mp),
            None => println!("None"),
        }
    }


    let (tx,rx) = mpsc::channel();

    let logout = thread::spawn(move || {
        let e = Environment::from_dir(Path::new("/tmp/usrtos")).unwrap();
        let logs = ULogs::from_env(&e);
        logs.reset();
        loop {
            let sig = rx.recv_timeout(time::Duration::from_millis(500)); 
            match sig {
                Err(mpsc::RecvTimeoutError::Timeout) => {
                    logs.dump();
                },
                _default => {break;},
            }
        }
    });

    let e = Environment::from_dir(Path::new("/tmp/usrtos"))?;
    let logt = ULogs::from_env(&e);
    for i in 0..100 {
        writeln!(*logt.error(),"this is {}",i);
    }
    logt.error().flush()?;
    thread::sleep(time::Duration::from_millis(5000));
    tx.send(0).unwrap();
    logout.join();
    Ok(())
    
}
